package app

import (
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"gopkg.in/yaml.v2"

	"my.com/mygo/models"
)

// ApplicationInfo 产品的环境配置
type ApplicationInfo struct {
	Name         string  `yaml:"name"`
	Version      float64 `yaml:"version"`
	ProductsRoot string  `yaml:"productsRoot"`
	ReleaseRoot  string  `yaml:"releaseRoot"`
}

// ApplicationProperties 产品的环境配置
type ApplicationProperties struct {
	ApplicationInfo ApplicationInfo `yaml:"applicationInfo"`
}

var (
	applicationProperties ApplicationProperties = ApplicationProperties{}
)

// GetApplicationProperties 获取环境配置
func GetApplicationProperties() *ApplicationProperties {

	if len(applicationProperties.ApplicationInfo.Name) > 0 {
		return &applicationProperties
	}

	// 获取程序的路径
	appPath := GetAppPath()
	file := filepath.Join(appPath, "conf", "application.yml")

	yamlFile, err := ioutil.ReadFile(file)
	if err != nil {
		log.Panicln(err)
	}

	if err := yaml.Unmarshal(yamlFile, &applicationProperties); err != nil {
		log.Panicln(err)
	}

	return &applicationProperties
}

// GetAppPath 获取程序的路径
func GetAppPath() string {
	// 首先尝试当前路径（开发调试）
	appPath := "."
	if checkAppPath(appPath) {
		return appPath
	}

	// 尝试启动目录
	ex, err := os.Executable()
	if err != nil {
		panic(err)
	}
	appPath = filepath.Dir(ex)
	if checkAppPath(appPath) {
		return appPath
	}

	// 尝试开发环境路径（单元测试）
	appPath = GetWorkspacePath()
	return appPath
}

// GetWorkspacePath 获取开发环境的根路径
func GetWorkspacePath() string {
	curDir, err := filepath.Abs("./")
	log.Println("application dir:" + curDir)
	if err != nil {
		log.Panic(err)
	}

	if checkAppPath(curDir) {
		return curDir
	}

	appPath := filepath.Join(curDir, "..")
	if checkAppPath(appPath) {
		return appPath
	}

	appPath = filepath.Join(curDir, "..", "..")
	if checkAppPath(appPath) {
		return appPath
	}

	panic(models.StatusModel{Code: -1, Message: "无法确定应用的根路径"})
}

// Exists reports whether the named file or directory exists.
func checkAppPath(appPath string) bool {
	file := filepath.Join(appPath, "conf", "application.yml")
	return Exists(file)
}

// Exists reports whether the named file or directory exists.
func Exists(name string) bool {
	if _, err := os.Stat(name); err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	return true
}
